package com.qire.manhua.model.viewModel.impl;

import android.content.Intent;
import android.graphics.Rect;
import android.view.View;

import com.qire.antsrouter.AntsRouter;
import com.qire.antsrouter.card.FloorCard;
import com.qire.common.SummerApp;
import com.qire.common.basic.ObjectUtil;
import com.qire.common.collect.ListUtil;
import com.qire.common.constant.Navigation;
import com.qire.common.support.AbsBringDialogViewModel;
import com.qire.common.support.base.IViewModel;
import com.qire.common.utils.EquipmentInfoUtil;
import com.qire.common.utils.ToastHelper;
import com.qire.common.widget.adapter.auto.AutoVariable;
import com.qire.common.widget.adapter.auto.SummerRecyclerBindAdapter;
import com.qire.common.widget.adapter.auto.annotation.AdapterEntityBind;
import com.qire.manhua.BR;
import com.qire.manhua.R;
import com.qire.manhua.activity.ComicDownloadSelectorActivity;
import com.qire.manhua.controller.ComicDownloadSelectorController;
import com.qire.manhua.dal.service.ComicDownloadSelectorService;
import com.qire.manhua.databinding.LayoutComicDownloadItemBatchBinding;
import com.qire.manhua.databinding.LayoutComicDownloadItemChapterBinding;
import com.qire.manhua.dialog.UnlockChapterOnComicDownloaderDialog;
import com.qire.manhua.dialog.VipDownloadPromptDialog;
import com.qire.manhua.model.entity.ComicBookEntity;
import com.qire.manhua.model.entity.ComicBookEntity.DirectoryInfo;
import com.qire.manhua.service.ComicDownloadService;

import java.util.ArrayList;
import java.util.Stack;

import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;
import androidx.lifecycle.MutableLiveData;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.Adapter;
import androidx.recyclerview.widget.RecyclerView.LayoutManager;
import androidx.recyclerview.widget.RecyclerView.ItemDecoration;

public class ComicDownloadSelectorViewModel extends AbsBringDialogViewModel implements IViewModel {

    private ComicDownloadSelectorService selectorService = new ComicDownloadSelectorService(this);

    private final Stack<DownloadSelectorBatchItemViewModel> selectorBatchList = new Stack<>();
    private final ArrayList<DownloadSelectorChapterItemViewModel> selectorChapterList = new ArrayList<>();

    private final SummerRecyclerBindAdapter selectorBatchAdapter = new SummerRecyclerBindAdapter(selectorBatchList);
    private final ItemDecoration[] selectorBatchItemDecorations = {new GridSpacingItemDecoration(4, EquipmentInfoUtil.dip2px(5), false)};
    private final SummerRecyclerBindAdapter selectorChapterAdapter = new SummerRecyclerBindAdapter(selectorChapterList);
    private final ItemDecoration[] selectorChapterItemDecorations = {new GridSpacingItemDecoration(4, EquipmentInfoUtil.dip2px(5), false)};

    private final ArrayList<String> chooseList = new ArrayList<>();
    private final ArrayList<String> needUnlockList = new ArrayList<>();
    private int vipFreeChapterCount = 0;

    private ComicBookEntity comicBookEntity;
    private ComicDownloadUnlockViewModel unlockViewModel;

    private ComicDownloadSelectorActivity activity;
    private ComicDownloadSelectorController controller;

    public ComicDownloadSelectorViewModel() {
        changeDownloadTipsVisible(View.VISIBLE);
        changeBatchChoosePanelVisible(View.GONE);
        refreshBatchPanelUI();
        refreshChooseQuantityTips();
    }

    @Override
    public int getVariableId() {
        return BR.comicDownloadSelectorViewModel;
    }

    //region    #附加管理 begin
    /**
     * 附加属性绑定
     * @param controller 事件控制器
     */
    public void onAddition(ComicDownloadSelectorActivity activity, ComicDownloadSelectorController controller) {
        this.activity = activity;
        this.controller = controller;
        this.selectorBatchAdapter.setEventProcess(controller);
        this.selectorChapterAdapter.setEventProcess(controller);
    }

    /**
     * 清理函数，在Activity退出时，ViewModel生命周期到期会被回收，调用该事件，
     * 页面由于切换、横竖屏转换、内存回收等情况并不会影响到ViewModel的生命周期。
     */
    @Override
    protected void onCleared() {
        super.onCleared();
        this.activity = null;
        this.controller = null;
        this.selectorService = null;
        this.selectorBatchAdapter.setEventProcess(null);
        this.selectorChapterAdapter.setEventProcess(null);
    }
    //endregion #附加管理 end

    //region #业务数据

    public ComicBookEntity comicBookEntity() {
        return comicBookEntity;
    }

    public int comicBookId() {
        return comicBookEntity.id;
    }

    public ArrayList<String> needUnlockList() {
        return needUnlockList;
    }

    public ArrayList<String> chooseList() {
        return chooseList;
    }

    /**
     * 重置所有数据列表
     */
    private void resetList() {
        selectorBatchList.clear();
        selectorChapterList.clear();
        chooseList.clear();
        needUnlockList.clear();
    }

    /**
     * 加载漫画实体，并填充目录项到选择器中
     * @param comicBookEntity 漫画实体
     */
    public void loadComicBookEntity(ComicBookEntity comicBookEntity) {
        this.comicBookEntity = comicBookEntity;
        resetList();
        selectorService.syncUpdateComicDirectoryInfo();
    }

    /**
     * 构建章节选择器子项目
     * @param directoryInfo 章节目录
     * @return 一个选择器子选择项
     */
    public DownloadSelectorChapterItemViewModel buildSelectorChapterItem(DirectoryInfo directoryInfo) {
        if(directoryInfo.canNotShow()) {
            return null;
        }
        DownloadSelectorChapterItemViewModel selectorChapterItem = new DownloadSelectorChapterItemViewModel(directoryInfo);
        selectorChapterList.add(selectorChapterItem);
        return selectorChapterItem;
    }

    /**
     * 构建批量选择器子项目，如果选择器为空或者当前子项以填满章节项则构建一个新的批量选择子项
     * @return 一个批量选择器子项
     */
    public DownloadSelectorBatchItemViewModel buildSelectorBatchItem() {
        DownloadSelectorBatchItemViewModel batchItemViewModel = selectorBatchList.isEmpty() ? null : selectorBatchList.lastElement();
        if(ObjectUtil.isNull(batchItemViewModel) || batchItemViewModel.isFill()) {
            batchItemViewModel = new DownloadSelectorBatchItemViewModel(selectorBatchList.size());
            selectorBatchList.add(batchItemViewModel);
        }
        return batchItemViewModel;
    }

    /**
     * 检查解锁或下载：
     * 如果下载列表中不存在需要解锁章节，则直接下载
     * 如果下载列表中存在需要解锁的章节，则处理解锁列表
     */
    public void checkUnlockOrDownload() {
        if(ListUtil.isEmpty(chooseList)) {
            ToastHelper.showToast("请选择下载章节");
            return;
        }

        if(ListUtil.notEmpty(needUnlockList)) {
            // 存在需要解锁的章节
            selectorService.handleBatchUnlockChapterList();
        } else {
            // 无需要解锁章节
            selectorService.handleComicBatchDownload();
        }
    }

    /**
     * 显示处理批量解锁章节列表的提示对话框；
     * 如果列表中存在会员免费章节，提示会员优惠信息
     * 如果列表准不存在会员免费章节，则提示解锁弹窗
     */
    public void showUnlockPromptDialog(float singlePrice, ComicDownloadUnlockViewModel unlockViewModel) {
        this.unlockViewModel = unlockViewModel;
        unlockViewModel.setCountInfo(chooseList.size(), needUnlockList.size());
        // todo: 叶婷婷确认过这个页面没有了删除的部分，当前版本2.4.5，之后3个版本内不恢复就彻底删除了
//        // 如果解锁列表里存在有会员免费的则弹出会员福利提示框否则弹出提示解锁对话框
//        if (vipFreeChapterCount > 0) {
//            float totalPrice = (vipFreeChapterCount * singlePrice);
//            new VipDownloadPromptDialog(activity, totalPrice, controller).show();
//        } else {
            showDownloadUnlockDialog();
//        }
    }

    /**
     * 显示下载解锁弹窗，批量解锁下载章节
     */
    public void showDownloadUnlockDialog() {
        new UnlockChapterOnComicDownloaderDialog(activity, controller, unlockViewModel).show();
    }

    public boolean isInsufficientBalance() {

        return unlockViewModel.isInsufficientBalance();
    }

    /**
     * 批量购买解锁章节
     */
    public void batchBuy() {
        if(ObjectUtil.nonNull(unlockViewModel)) {
            selectorService.batchBuy(unlockViewModel.originalPrice());
        } else {
            ToastHelper.showToast("数据异常，请重试");
        }
    }

    public void startDownloadService() {
        int[] chapterIds = new int[chooseList.size()];

        for(int index = 0; index < chapterIds.length; index++) {
            chapterIds[index] = Integer.valueOf(chooseList.get(index));
        }

        ComicDownloadService.startService(SummerApp.summerApp(), ComicDownloadService.ACTION_START, chapterIds);
        AntsRouter.ROUTER.<FloorCard>buildCard(Navigation.Page.ComicDownloadProgressPage)
                .withData("comicBookEntity", comicBookEntity)
                .withFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
                .navigation();

    }

    //endregion #业务数据

    //region #UI操作

    public void refreshUI() {
        changeDownloadTipsVisible(View.VISIBLE);
        changeBatchChoosePanelVisible(View.GONE);
        refreshBatchPanelUI();
        refreshChooseQuantityTips();

        selectorBatchAdapter.notifyDataSetChanged();
        selectorChapterAdapter.notifyDataSetChanged();
    }

    public void changeDownloadTipsVisible(int visible) {
        int marginTopDp = visible == View.VISIBLE ? 95 : 45;
        set("comicDownloadTipsVisible", visible);
        set("selectorMarginTop", EquipmentInfoUtil.dip2px(marginTopDp));
    }

    public void changeBatchChoosePanelVisible(int visible) {
        set("batchChoosePanelVisible", visible);
    }

    public void refreshBatchPanelUI() {
        set("batchChooseDownloadBtnText", needUnlockList.isEmpty() ? "立即下载" : "购买下载");
    }

    public void refreshChooseQuantityTips() {
        boolean noChoose = chooseList.isEmpty();
        set("chooseQuantityTips", "您已选" + chooseList.size() + "话, 包括" + needUnlockList.size() + "集收费章节，需支付开通");
        set("downloadBtnTextColor", noChoose ? "#ff666666" : "#ffff9024");
        set("downloadBtnIconResource", noChoose ? R.drawable.app_comic_download_icon_down_a : R.drawable.app_comic_download_icon_down_b);
    }

    /**
     * 取消所有选择项
     */
    public void clearAllChoose() {
        for (DownloadSelectorChapterItemViewModel chapterItem : selectorChapterList) {
            if (chapterItem.haveChose) {
                chapterItem.toggleChoose();
            }
        }
    }

    //endregion #UI操作

    //region #UI绑定

    public MutableLiveData<Integer> getComicDownloadTipsVisible() {
        return get("comicDownloadTipsVisible");
    }

    public MutableLiveData<Integer> getSelectorMarginTop() {
        return get("selectorMarginTop");
    }

    public MutableLiveData<CharSequence> getChooseQuantityTips() {
        return get("chooseQuantityTips");
    }

    public MutableLiveData<String> getDownloadBtnTextColor() {
        return get("downloadBtnTextColor");
    }

    public MutableLiveData<Integer> getDownloadBtnIconResource() {
        return get("downloadBtnIconResource");
    }

    public MutableLiveData<Integer> getBatchChoosePanelVisible() {
        return get("batchChoosePanelVisible");
    }

    public MutableLiveData<CharSequence> getBatchChooseDownloadBtnText() {
        return get("batchChooseDownloadBtnText");
    }

    public Adapter getSelectorBatchAdapter() {
        return selectorBatchAdapter;
    }

    public LayoutManager getSelectorBatchLayoutManager() {
        return new GridLayoutManager(null, 4);
    }

    public ItemDecoration[] getSelectorBatchItemDecorations() {
        return selectorBatchItemDecorations;
    }

    public Adapter getSelectorChapterAdapter() {
        return selectorChapterAdapter;
    }

    public LayoutManager getSelectorChapterLayoutManager() {
        return new GridLayoutManager(null, 4);
    }

    public ItemDecoration[] getSelectorChapterItemDecorations() {
        return selectorChapterItemDecorations;
    }

    //endregion #UI绑定

    @AdapterEntityBind(viewRid = R.layout.layout_comic_download_item_chapter)
    public class DownloadSelectorChapterItemViewModel extends BaseObservable implements AutoVariable<LayoutComicDownloadItemChapterBinding> {

        private final DirectoryInfo directoryInfo;
        private boolean haveChose       = false;
        private boolean haveDownloaded  = false;

        private DownloadSelectorBatchItemViewModel batchItemViewModel;

        public DownloadSelectorChapterItemViewModel(DirectoryInfo directoryInfo){
            this.directoryInfo  = directoryInfo;
        }

        @Override
        public void bindVariable(LayoutComicDownloadItemChapterBinding viewBind) {
            viewBind.setDownloadSelectorChapterItemViewModel(this);
        }

        /**
         * 切换选择状态
         */
        public void toggleChoose() {
            // 已下载缓存过的不做任何处理
            if(haveDownloaded) {
                return;
            }
            haveChose = !haveChose;
            if(haveChose) {
                chooseList.add(String.valueOf(directoryInfo.chapterId));            // 选中的章节，加入选择列表
                if(directoryInfo.haveDownloadLock()) {                              // 需要解锁
                    needUnlockList.add(String.valueOf(directoryInfo.chapterId));    // 加入解锁列表
                    if(directoryInfo.isVipFree) {                                   // 是会员免费
                        vipFreeChapterCount++;                                      // 累加会员免费计数
                    }
                }
            } else {
                chooseList.remove(String.valueOf(directoryInfo.chapterId));         // 取消的章节，从选择列表移除
                if(directoryInfo.haveDownloadLock()) {                              // 需要解锁
                    needUnlockList.remove(String.valueOf(directoryInfo.chapterId)); // 移除解锁列表
                    if(directoryInfo.isVipFree) {                                   // 是会员免费
                        vipFreeChapterCount--;                                      // 累减计数
                    }
                }
            }

            // UI更新通知：
            // 1、刷新章节选择器中当前节点状态
            // 2、刷新选择数量提示面板的状态
            // 3、刷新批量选择器中当前节点关联节点状态
            notifyChange();
            refreshChooseQuantityTips();
            if(ObjectUtil.nonNull(batchItemViewModel)) {
                batchItemViewModel.choseAccumulateCount(haveChose);
            }
        }

        public void existDownloaded() {
            haveDownloaded = true;
        }

        @Bindable
        public int getDownloadedBuoyVisible() {
            return haveDownloaded ? View.VISIBLE : View.GONE;
        }
        @Bindable
        public int getUnlockedBuoyVisible() {
            if(haveDownloaded) {
                return View.GONE;
            }
            if(directoryInfo.notNeedBuy()) {
                return View.GONE;
            }
            return View.VISIBLE;
        }
        @Bindable
        public int getUnlockedIconResource() {
            if(directoryInfo.isVipFree) {
                return haveChose ? R.drawable.app_comic_download_icon_vip_a : R.drawable.app_comic_download_icon_vip_b;
            }
            if(!directoryInfo.haveLock()) {
                return haveChose ? R.drawable.app_comic_download_icon_unlocked_a : R.drawable.app_comic_download_icon_unlocked_b;
            }
            return haveChose ? R.drawable.app_comic_download_icon_locked_a : R.drawable.app_comic_download_icon_locked_b;
        }
        @Bindable
        public String getChapterNumberTextColor() {
            if(haveDownloaded) {
                return "#808080";
            }
            return haveChose ? "#ffffff" : "#333333";
        }
        @Bindable
        public String getChapterNumberText() {
            return String.valueOf(directoryInfo.serialId);
        }
        @Bindable
        public int getItemBackgroundResource() {
            if(haveDownloaded) {
                return R.drawable.app_comic_download_item_bg_cached;
            }
            if(haveChose) {
                return R.drawable.app_comic_download_item_bg_selected;
            }
            return R.drawable.app_comic_download_item_bg_normal;
        }


    }

    @AdapterEntityBind(viewRid = R.layout.layout_comic_download_item_batch)
    public class DownloadSelectorBatchItemViewModel extends BaseObservable implements AutoVariable<LayoutComicDownloadItemBatchBinding> {

        public static final int groupSize = 30;
        public final int batchNumber;

        private DownloadSelectorChapterItemViewModel[]  chapterGroupViewModel = new DownloadSelectorChapterItemViewModel[groupSize];
        private boolean haveDownloaded  = false;
        private int     cursor          = 0;
        private int     choseCount      = 0;

        public DownloadSelectorBatchItemViewModel(int batchNumber) {
            this.batchNumber = batchNumber;
        }

        @Override
        public void bindVariable(LayoutComicDownloadItemBatchBinding viewBind) {
            viewBind.setDownloadSelectorBatchItemViewModel(this);
        }

        /**
         * 批量组是否已存满
         * @return true 已填满 false 未填满
         */
        public boolean isFill() {
            return cursor >= groupSize;
        }

        /**
         * 添加批量组章节项，并绑定
         * @param chapterViewModel 章节项
         */
        public void addChapterViewModel(DownloadSelectorChapterItemViewModel chapterViewModel) {
            chapterGroupViewModel[cursor] = chapterViewModel;
            chapterViewModel.batchItemViewModel = this;
            cursor++;
        }

        /**
         * 批量选择项状态
         * @return 只要有子项被选择，则视为选择
         */
        public boolean haveChose() {
            //haveChose
            return choseCount >= cursor;
//            return choseCount > 0;
        }

        /**
         * 选择累计
         * @param haveChose
         */
        public void choseAccumulateCount(boolean haveChose) {
            choseCount += haveChose ? 1 : -1;
            notifyChange();
            refreshBatchPanelUI();
        }

        /**
         * 切换批量选中状态
         */
        public void toggleChoose() {

            final boolean haveChose = !haveChose();

            for(int index = 0; index < cursor; index++) {
                if(chapterGroupViewModel[index] == null) {
                    continue;
                }
                if(haveChose == chapterGroupViewModel[index].haveChose) {
                    continue;
                }
                chapterGroupViewModel[index].toggleChoose();
            }
            notifyChange();
            refreshBatchPanelUI();
        }

        @Bindable
        public int getBuoyVisible() {
            return haveDownloaded ? View.VISIBLE : View.GONE;
        }

        @Bindable
        public String getChapterNumberTextColor() {
            if(haveDownloaded) {
                return "#808080";
            }
            return haveChose() ? "#ffffff" : "#333333";
        }

        @Bindable
        public String getChapterNumberText() {
            int startNumber = (batchNumber) * groupSize + 1;
            StringBuilder batchNumberText = new StringBuilder();
            batchNumberText.append(startNumber).append("-").append(startNumber + cursor - 1);
            return batchNumberText.toString();
        }

        @Bindable
        public int getItemBackgroundResource() {
            if(haveDownloaded) {
                return R.drawable.app_comic_download_item_bg_cached;
            }
            if(haveChose()) {
                return R.drawable.app_comic_download_item_bg_selected;
            }
            return R.drawable.app_comic_download_item_bg_normal;
        }

    }

    public class GridSpacingItemDecoration extends ItemDecoration {

        private int spanCount;
        private int spacing;
        private boolean includeEdge;

        public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
            this.spanCount = spanCount;
            this.spacing = spacing;
            this.includeEdge = includeEdge;
        }

        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            int position = parent.getChildAdapterPosition(view); // item position
            int column = position % spanCount; // item column

            if (includeEdge) {
                outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
                outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)

                if (position < spanCount) { // top edge
                    outRect.top = spacing;
                }
                outRect.bottom = spacing; // item bottom
            } else {
                outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
                outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f /    spanCount) * spacing)
                if (position >= spanCount) {
                    outRect.top = spacing; // item top
                }
            }
        }
    }

}
